﻿using Core.Utility.Attributes;
using Core.Utility.Extendsions.Json;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace Core.Utility.Helper
{
    /// <summary>
    /// 扩展方法助手类
    /// </summary>
    public static class ExtensionMethodHelper
    {
        #region Dictionary
        /// <summary>
        /// 字典新增或更新
        /// </summary>
        /// <param name="dic"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns>新增返回true，更新返回false</returns>
        public static bool AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dic, TKey key, TValue value)
        {
            if (dic.ContainsKey(key))
            {
                dic[key] = value;                
                return false;
            }
            else
            {
                dic.Add(key, value);
                return true;
            }
        }

        /// <summary>
        /// 尝试字典新增，判断Key值是否存在，存在则不新增
        /// </summary>
        /// <param name="dic"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns>成功返回true，失败返回false</returns>
        public static bool TryAdd<TKey, TValue>(this IDictionary<TKey, TValue> dic, TKey key, TValue value)
        {
            if (!dic.ContainsKey(key))
            {
                dic[key] = value;
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 尝试字典新增列列表，判断Key值是否存在，存在则不新增
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dic"></param>
        /// <param name="items"></param>
        public static void TryAddRange<TKey, TValue>(this IDictionary<TKey, TValue?> dic, Dictionary<TKey, TValue?> items)
            where TKey : IEquatable<TKey>
        {
            foreach(var item in items)
            {
                dic.TryAdd(item.Key, item.Value);
            }
        }

        /// <summary>
        /// 尝试字典新增列列表，判断Key值是否存在，存在则更新
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dic"></param>
        /// <param name="items"></param>
        public static void TryAddOrUpdateRange<TKey, TValue>(this IDictionary<TKey, TValue?> dic, Dictionary<TKey, TValue?> items)
            where TKey: IEquatable<TKey>
        {
            foreach (var item in items)
            {
                dic.AddOrUpdate(item.Key, item.Value);
            }
        }

        /// <summary>
        /// 转换为CheckComBoxCtrl的ItemSource
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dic"></param>
        /// <returns></returns>
        public static DataTable ToCheckComBoxCtrlItemSource<TKey, TValue>(this Dictionary<TKey, TValue?> dic)
            where TKey : IEquatable<TKey>
        {
            DataTable source = new DataTable();
            source.AddColumn("IsChecked","选择",typeof(bool));
            source.AddColumn("Key","键", typeof(string));
            source.AddColumn("Value","值", typeof(string));
            if (dic != null) 
            {
                foreach (KeyValuePair<TKey, TValue?> keyValuePair in dic)
                {
                    DataRow row = source.NewRow();
                    row["IsChecked"] = false;
                    row["Key"] = keyValuePair.Key?.ToString();
                    row["Value"] = keyValuePair.Value?.ToString();
                    source.Rows.Add(row);
                }
            }
            return source;
        }

        /// <summary>
        /// 转IList&lt;string&gt;
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dic"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static IList<string> ToList<TKey, TValue>(this IDictionary<TKey, TValue> dic, string separator = ",")
        {
            List<string> res = new List<string>();
            if (dic != null)
            {
                foreach (var item in dic)
                {
                    res.Add($"{item.Key?.ToString()}{separator}{item.Value?.ToString()}");
                }
            }
            return res;
        }

        /// <summary>
        /// 转IList&lt;string&gt; 将键值对以指定字符串格式拼接
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dic"></param>
        /// <param name="isValueKey">是否以Value-Key形式拼接</param>
        /// <param name="separatorLeft">拼接符左，始终拼接第二个位置</param>
        /// <param name="separatorRight">拼接符右,始终拼接第二个位置</param>
        /// <returns></returns>
        public static IList<string> ToValueKeyList<TKey, TValue>(this IDictionary<TKey, TValue> dic,bool isValueKey = true, string separatorLeft = "(",string separatorRight=")")
        {
            List<string> res = new List<string>();
            if (dic != null)
            {
                foreach (var item in dic)
                {
                    if (isValueKey)
                    {
                        res.Add($"{item.Value?.ToString()}{separatorLeft}{item.Key?.ToString()}{separatorRight}");
                    }
                    else
                    {
                        res.Add($"{item.Key?.ToString()}{separatorLeft}{item.Value?.ToString()}{separatorRight}");
                    }
                }
            }
            return res;
        }
        #endregion Dictionary        

        #region List
        /// <summary>
        /// IList&lt;string&gt; 值前后添加字符
        /// </summary>
        /// <param name="list"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        public static IList<string> ValueAddBeforeAfterCharacter(this IList<string> list, string str)
        {
            List<string> res = new List<string>();
            foreach(var item in list)
            {
                res.Add($"{str}{item}{str}");
            }
            return res;
        }

        /// <summary>
        /// IList&lt;string&gt;  移除空值
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public static IList<T> RemoveNullValue<T>(this IList<T> list)
        {
            List<T> res = new List<T>();
            foreach (var item in list)
            {
                if(item != null && !string.IsNullOrEmpty(item?.ToString()))
                {
                    res.Add(item);
                }
            }
            return res;
        }

        /// <summary>
        /// 添加全部数据项，通常用于下拉筛选使用;
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="allDataItem">所有数据项，若该项在 参数list中已存在，将不再新增；</param>
        /// <returns></returns>
        public static IList<T> AddAllDataItem<T>(this IList<T> list,T allDataItem)
        {
            if(list != null)
            {
                if (!list.Contains(allDataItem))
                {
                    list.Insert(0, allDataItem);
                }
            }
            else
            {
                list = new List<T>();
                list.Add(allDataItem);
            }
            return list;
        }

        /// <summary>
        /// 转字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static string ToString<T>(this IList<T> list,string separator = ",")
        {
            string res = "";
            if(list != null)
            {
                res = string.Join(separator, list);
            }
            return res;
        }

        /// <summary>
        /// 尝试List新增，判断新增的值是否存在，存在则不新增
        /// </summary>
        /// <param name="list"></param>
        /// <param name="data"></param>
        /// <returns>成功返回true，失败返回false</returns>
        public static bool TryAdd<TData>(this List<TData> list,TData data)
        {
            if (!list.Contains(data))
            {
                list.Add(data);
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion

        #region   ObservableCollection

        /// <summary>
        /// 尝试ObservableCollection新增，判断新增的值是否存在，存在则不新增
        /// </summary>
        /// <param name="list"></param>
        /// <param name="data"></param>
        /// <returns>成功返回true，失败返回false</returns>
        public static bool TryAdd<TData>(this ObservableCollection<TData> list, TData data)
        {
            if (!list.Contains(data))
            {
                list.Add(data);
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion  ObservableCollection

        #region DataTable DataSet

        /// <summary>
        /// 属性-值 转DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="args"></param>
        /// <param name="tableNamePrefix">tableNamePrefix</param>
        /// <returns></returns>
        public static DataSet PropertyValueToDataSet<T>(this IList<T> args, string tableNamePrefix = "table") where T : class
        {
            DataSet dataSet = new DataSet();
            if (!string.IsNullOrEmpty(tableNamePrefix))
            {
                tableNamePrefix = $"{tableNamePrefix}_";
            }
            else
            {
                tableNamePrefix = "table_";
            }
            if (args != null)
            {
                int sn = 0;
                foreach (var item in args)
                {
                    sn++;
                    dataSet.Tables.Add(item.PropertyValueToDataTable($"{tableNamePrefix}{sn}").Copy());
                }
            }
            return dataSet;
        }

        /// <summary>
        /// 属性-值 转DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="args"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public static DataTable PropertyValueToDataTable<T>(this T args, string tableName = "") where T : class
        {
            DataTable dt = new DataTable();
            if (!string.IsNullOrEmpty(tableName))
            {
                dt.TableName = tableName;
            }
            DataColumn dcTitle = new DataColumn("字段名", typeof(string));
            dt.Columns.Add(dcTitle);
            DataColumn dcDesc = new DataColumn("字段说明", typeof(string));
            dt.Columns.Add(dcDesc);
            DataColumn dcValue = new DataColumn("字段值", typeof(string));
            dt.Columns.Add(dcValue);
            if (args != null)
            {
                PropertyInfo[] pArray = args.GetType().GetProperties();
                if (pArray != null && pArray.Count() > 0)
                {
                    foreach (var p in pArray)
                    {
                        //获取描述
                        object[] attrsDesc = p.GetCustomAttributes(typeof(DescriptionAttribute), false);
                        string name = p.Name;
                        string? desc = "";
                        if (attrsDesc != null && attrsDesc.Count() > 0)
                        {
                            desc = (attrsDesc.First() as DescriptionAttribute)?.Description;
                        }
                        DataRow dr = dt.NewRow();
                        string? value = p.GetValue(args, null)?.ToString();
                        dr[dcTitle] = name;
                        dr[dcDesc] = desc;
                        dr[dcValue] = value;
                        dt.Rows.Add(dr);
                    }
                }
            }
            return dt;
        }

        /// <summary>
        /// DataRowView转指定类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="row"></param>
        /// <returns></returns>
        public static T ToPropertyValue<T>(this DataRowView? row) where T : new()
        {
            return ToPropertyValue<T>(row?.Row);
        }

        /// <summary>
        /// DataRow转指定类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="row"></param>
        /// <returns></returns>
        public static T ToPropertyValue<T>(this DataRow? row) where T : new()
        {
            var sd = new T();
            if (row != null)
            {
                var type = typeof(T);
                var pps = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                var prs = pps.Where(i => i.CanWrite).ToList();
                if (prs.Count > 0)
                {
                    foreach (DataColumn item in row.Table.Columns)
                    {
                        var pr = prs.Where(p => p.Name == item.ColumnName).FirstOrDefault();
                        if (pr != null)
                        {
                            object val = row[item];
                            try
                            {
                                try
                                {
                                    val = Convert.ChangeType(val, pr.PropertyType.GetGenericType());
                                }
                                catch
                                {

                                }
                                pr.SetValue(sd, val, null);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine($"{pr.PropertyType.Name}数据写入类型不匹配,{ex.Message}");
                            }
                        }
                    }
                }
            }
            return sd;
        }

        /// <summary>
        /// 获取泛型类型定义的 System.Type 对象
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static Type GetGenericType(this Type type)
        {
            Type res = type;
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                // If it is NULLABLE, then get the underlying type. eg if "Nullable<int>" then this will return just "int"
                res = type.GetGenericArguments()[0];
            }
            return res;
        }

        /// <summary>
        /// T 转为 DataRow
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item"></param>
        /// <returns></returns>
        public static DataRow? ToDataRow<T>(this T item) where T : new()
        {
            try
            {
                DataTable dataTable = ToDataTable<T>(new List<T>() { item });
                if (dataTable != null && dataTable.Rows.Count > 0)
                {
                    return dataTable.Rows[0];
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"将Model转为DataRow出错：{Environment.NewLine}" + ex.Message, ex);
            }
        }


        /// <summary>
        /// 通过特性 将 IList&lt;T&gt; 转为 转为 DataRow
        /// <see cref="DataTable.TableName"/>优先通过<see cref="DescriptionAttribute"/>属性获得
        /// <see cref="DataColumn"/>属性优先通过<see cref="DataColumnAttribute"/>属性获得
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item"></param>
        /// <returns></returns>
        public static DataRow? ToDataRowByAttribute<T>(this T item) where T : new()
        {
            try
            {
                DataTable dataTable = ToDataTableByAttribute<T>(new List<T>() { item });
                if (dataTable != null && dataTable.Rows.Count > 0)
                {
                    return dataTable.Rows[0];
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"将Model转为DataRow出错：{Environment.NewLine}" + ex.Message, ex);
            }
        }

        /// <summary>
        /// 将 IList&lt;T&gt; 转为 DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="items"></param>
        /// <returns></returns>
        public static DataTable ToDataTable<T>(this IList<T> items) where T : new()
        {
            try
            {
                Type type = typeof(T);
                DataTable table = new DataTable();
                table.TableName = type.Name;
                PropertyInfo[] propertyInfos = type.GetProperties();
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    if (!table.Columns.Contains(propertyInfo.Name))
                    {
                        Type columnType = GetCoreType(propertyInfo.PropertyType) ?? typeof(object);
                        DataColumn column = new DataColumn(propertyInfo.Name, columnType);
                        //if (items.Count > 0)
                        //{
                        //    string columnCaption = GetDescriptionAttribute(items[0], propertyInfo.Name);
                        //    if (!string.IsNullOrEmpty(columnCaption))
                        //    {
                        //        column.Caption = columnCaption;
                        //    }
                        //}
                        string? columnCaption = GetDescriptionAttribute(new T(), propertyInfo.Name);
                        if (!string.IsNullOrEmpty(columnCaption))
                        {
                            column.Caption = columnCaption;
                        }
                        table.Columns.Add(column);
                    }
                }

                foreach (T item in items)
                {
                    object[] values = new object[propertyInfos.Length];
                    for (int i = 0; i < propertyInfos.Length; i++)
                    {
                        var value = propertyInfos[i].GetValue(item, null);
                        if (value == null)
                        {
                            value = DBNull.Value;
                        }
                        values[i] = value;
                    }
                    table.Rows.Add(values);
                }
                return table;
            }
            catch (Exception ex)
            {
                throw new Exception($"将List<Model>转换为DataTable出错：{Environment.NewLine}{ex.Message}", ex);
            }
        }


        /// <summary>
        /// 通过特性 将 IList&lt;T&gt; 转为 转为 DataTable
        /// <see cref="DataTable.TableName"/>优先通过<see cref="DescriptionAttribute"/>属性获得
        /// <see cref="DataColumn"/>属性优先通过<see cref="DataColumnAttribute"/>属性获得
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="items"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static DataTable ToDataTableByAttribute<T>(this IList<T> items) where T : new()
        {
            try
            {
                Type type = typeof(T);
                DataTable table = new DataTable();
                string? tableName = AttributeExtendsionHelper.GetMemberInfoAttribute<DescriptionAttribute>(type)?.Description;
                if(!string.IsNullOrEmpty(tableName))
                {
                    table.TableName = tableName;
                }
                else
                {
                    table.TableName = type.Name;
                }
                PropertyInfo[] propertyInfos = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic);
                List<DataColumnAttribute> dcaList = new List<DataColumnAttribute>();
                int iOrder = 0;
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    DataColumnAttribute dca = AttributeExtendsionHelper.GetPropertyFirstAttribute<DataColumnAttribute>(typeof(T), propertyInfo.Name) ?? new DataColumnAttribute(ignore: true);
                    if(dca.Order == 0)
                    {
                        iOrder++;
                        dca.Order = int.MaxValue - propertyInfos.Length - 1 + iOrder;
                    }
                    dca.ColumnName = string.IsNullOrEmpty(dca.ColumnName) ? propertyInfo.Name : dca.ColumnName;
                    dca.PropertyName = propertyInfo.Name;
                    dca.DataType = dca.DataType ?? GetCoreType(propertyInfo.PropertyType) ?? typeof(object);
                    dca.Caption = string.IsNullOrEmpty(dca.Caption) ? GetDescriptionAttribute(new T(), propertyInfo.Name) : dca.Caption;
                    dcaList.Add(dca);
                }                
                dcaList = dcaList.Where(p=>p.Ignore == false).OrderBy(p => p.Order).ToList();
                foreach(var dcaItem in dcaList)
                {
                    if(string.IsNullOrEmpty(dcaItem.ColumnName) == false && !table.Columns.Contains(dcaItem.ColumnName ?? ""))
                    {
                        DataColumn dc = new DataColumn();
                        dc.Caption = dcaItem.Caption;
                        dc.DataType = dcaItem.DataType;
                        dc.ColumnName = dcaItem.ColumnName;
                        dc.Expression = dcaItem.Expression;
                        dc.AllowDBNull = dcaItem.AllowDBNull;
                        dc.AutoIncrement = dcaItem.AutoIncrement;
                        dc.AutoIncrementSeed = dcaItem.AutoIncrementSeed;
                        dc.AutoIncrementStep = dcaItem.AutoIncrementStep;
                        dc.ColumnMapping = dcaItem.ColumnMapping;
                        dc.DateTimeMode = dcaItem.DateTimeMode;
                        dc.DefaultValue = dcaItem.DefaultValue ?? dc.DefaultValue;
                        dc.MaxLength = dcaItem.MaxLength;
                        dc.Namespace = dcaItem.Namespace ?? dc.Namespace;
                        dc.Prefix = dcaItem.Prefix ?? dc.Prefix;
                        dc.ReadOnly = dcaItem.ReadOnly;
                        dc.Unique = dcaItem.Unique;
                        table.Columns.Add(dc);
                    }
                }
                //根据dca列表，生成列
                foreach (T item in items)
                {
                    DataRow row = table.NewRow();
                    foreach(var  dcItem in dcaList)
                    {
                        object? propertyValue = propertyInfos.FirstOrDefault(p=>p.Name == dcItem.PropertyName)?.GetValue(item, null);
                        if(propertyValue == null)
                        {
                            if(dcItem.AllowDBNull)
                            {
                                row[dcItem.ColumnName ?? ""] = DBNull.Value;
                            }
                            else
                            {
                                try
                                {
                                    row[dcItem.ColumnName ?? ""] = null;
                                }
                                catch
                                {

                                }
                            }
                        }
                        else
                        {
                            row[dcItem.ColumnName ?? ""] = propertyValue;
                        }
                    }
                    table.Rows.Add(row);
                }
                return table;
            }
            catch (Exception ex)
            {
                throw new Exception($"将List<Model>转换为DataTable出错：{Environment.NewLine}{ex.Message}", ex);
            }
        }

        /// <summary>
        /// DataColumn ColumnName和Caption交换
        /// </summary>
        /// <param name="table"></param>
        /// <param name="isColumnNameToCaption">true:ColumnName To Caption;false: Caption To ColumnName</param>
        /// <returns></returns>
        public static DataTable DataColumnNameExchangeCaption(this DataTable table,bool isColumnNameToCaption = true)
        {
            try
            {
                DataTable changeTable = table.Copy();
                foreach(DataColumn dc in changeTable.Columns)
                {
                    string nameOrCaption = dc.ColumnName;
                    if(isColumnNameToCaption == true)
                    {
                        dc.ColumnName = dc.Caption;
                        dc.Caption = nameOrCaption;                        
                    }
                    else
                    {
                        nameOrCaption = dc.Caption;
                        dc.Caption = dc.ColumnName;
                        dc.ColumnName = nameOrCaption;
                    }
                }
                return changeTable;
            }
            catch
            {
                return table;
            }
        }

        /// <summary>
        /// 将 DataTable 转为IList&lt;string&gt; 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="table"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static List<T>? ToListModel<T>(this DataTable table, List<T>? defaultValue = null) where T : class, new()
        {
            try
            {
                List<T> res = new List<T>();
                Type type = typeof(T);
                string tempName = "";
                foreach (DataRow row in table.Rows)
                {
                    T t = new T();
                    // 获得此模型的公共属性      
                    PropertyInfo[] propertys = t.GetType().GetProperties();
                    foreach (PropertyInfo pi in propertys)
                    {
                        tempName = pi.Name;  // 检查DataTable是否包含此列    
                        if (table.Columns.Contains(tempName))
                        {
                            // 判断此属性是否有Setter      
                            if (!pi.CanWrite)
                            {
                                continue;
                            }
                            object value = row[tempName];
                            if (value != DBNull.Value)
                            {
                                pi.SetValue(t, value, null);
                            }
                        }
                    }
                    res.Add(t);
                }
                return res;
            }
            catch
            {
                return defaultValue;
            }
        }


        /// <summary>
        /// 通过特性 将 DataTable 转为IList&lt;string&gt; 
        /// <see cref="DataTable.TableName"/>优先通过<see cref="DescriptionAttribute"/>属性获得
        /// <see cref="DataColumn"/>属性优先通过<see cref="DataColumnAttribute"/>属性获得
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="table"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static List<T>? ToListModelByAttribute<T>(this DataTable table, List<T>? defaultValue = null) where T : class, new()
        {
            try
            {
                List<T> res = new List<T>();
                Type type = typeof(T);
                PropertyInfo[] propertyInfos = type.GetProperties();
                List<DataColumnAttribute> dcaList = new List<DataColumnAttribute>();
                int iOrder = 0;
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    DataColumnAttribute dca = AttributeExtendsionHelper.GetPropertyFirstAttribute<DataColumnAttribute>(typeof(T), propertyInfo.Name) ?? new DataColumnAttribute(ignore: true);
                    if (dca.Order == 0)
                    {
                        iOrder++;
                        dca.Order = int.MaxValue - propertyInfos.Length - 1 + iOrder;
                    }
                    dca.ColumnName = string.IsNullOrEmpty(dca.ColumnName) ? propertyInfo.Name : dca.ColumnName;
                    dca.PropertyName = propertyInfo.Name;
                    dca.DataType = dca.DataType ?? GetCoreType(propertyInfo.PropertyType) ?? typeof(object);
                    dca.Caption = string.IsNullOrEmpty(dca.Caption) ? GetDescriptionAttribute(new T(), propertyInfo.Name) : dca.Caption;
                    dcaList.Add(dca);
                }
                foreach (DataRow row in table.Rows)
                {
                    T t = new T();
                    // 获得此模型的公共属性      
                    foreach (PropertyInfo pi in propertyInfos)
                    {
                        string columnName = dcaList.FirstOrDefault(p => p.PropertyName == pi.Name)?.ColumnName ?? "";
                        if (string.IsNullOrEmpty(columnName))
                        { 
                            columnName = pi.Name;
                        }
                        // 检查DataTable是否包含此列    
                        if (table.Columns.Contains(columnName))
                        {
                            // 判断此属性是否有Setter      
                            if (!pi.CanWrite)
                            {
                                continue;
                            }                            
                            object value = row[columnName];
                            if (value != DBNull.Value)
                            {
                                pi.SetValue(t, value, null);
                            }
                        }
                    }
                    res.Add(t);
                }
                return res;
            }
            catch
            {
                return defaultValue;
            }
        }


        /// <summary>
        /// 将 DataTable 的最后一行数据 转为 T
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="table"></param>
        /// <returns></returns>
        public static T? ToModel<T>(this DataTable table) where T : class, new()
        {
            try
            {
                DataTable lastRowTable = table.Clone();
                if (table.Rows.Count > 1)
                {
                    lastRowTable.Rows.Add(table.Rows[table.Rows.Count - 1]);
                    return ToListModel<T>(table)?.FirstOrDefault();
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"将DataTable转为DataModel失败,{Environment.NewLine}" + ex.Message, ex);
            }
        }



        /// <summary>
        /// 通过特性 将 DataTable 转为IList&lt;string&gt; 
        /// <see cref="DataTable.TableName"/>优先通过<see cref="DescriptionAttribute"/>属性获得
        /// <see cref="DataColumn"/>属性优先通过<see cref="DataColumnAttribute"/>属性获得
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="table"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static T? ToModelByAttribute<T>(this DataTable table, T? defaultValue = null) where T : class, new()
        {
            try
            {
                DataTable lastRowTable = table.Clone();
                if (table.Rows.Count > 1)
                {
                    lastRowTable.Rows.Add(table.Rows[table.Rows.Count - 1]);
                    return ToListModelByAttribute<T>(table)?.FirstOrDefault();
                }
                else
                {
                    return defaultValue;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"将DataTable转为DataModel失败,{Environment.NewLine}" + ex.Message, ex);
            }
        }

        /// <summary>
        /// 将 DataRow 转为 T
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="row"></param>
        /// <returns></returns>
        public static T? ToModel<T>(this DataRow row) where T : class, new()
        {
            try
            {
                if (row != null)
                {
                    DataTable table = row.Table.Clone();
                    table.Rows.Add(row.ItemArray);
                    return ToModel<T>(table);
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"将DataRow转为DataModel失败,{Environment.NewLine}" + ex.Message, ex);
            }
        }

        /// <summary>
        /// 通过特性 将 DataTable 转为IList&lt;string&gt; 
        /// <see cref="DataTable.TableName"/>优先通过<see cref="DescriptionAttribute"/>属性获得
        /// <see cref="DataColumn"/>属性优先通过<see cref="DataColumnAttribute"/>属性获得
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="row"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static T? ToModelByAttribute<T>(this DataRow row, T? defaultValue = null) where T : class, new()
        {
            try
            {
                if (row != null)
                {
                    DataTable table = row.Table.Clone();
                    table.Rows.Add(row.ItemArray);
                    return ToModelByAttribute<T>(table);
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"将DataRow转为DataModel失败,{Environment.NewLine}" + ex.Message, ex);
            }
        }

        /// <summary>
        /// DataRow转输出字符串
        /// </summary>
        /// <returns></returns>
        public static string? ToOutputString(this DataRow? row, string separator = ",")
        {
            StringBuilder content = new StringBuilder();
            List<string?> columnString = new List<string?>();
            List<string?> columnNameString = new List<string?>();

            if (row != null)
            {
                foreach (DataColumn dataColumn in row.Table.Columns)
                {
                    if (dataColumn.Caption != dataColumn.ColumnName)
                    {
                        columnNameString.Add($"{dataColumn.ColumnName}({dataColumn.Caption})");
                    }
                    else
                    {
                        columnNameString.Add(dataColumn.ColumnName);
                    }
                    columnString.Add(row[dataColumn] == null ? "" : row[dataColumn].ToString());
                }
                if (columnNameString.Count > 0)
                {
                    content.AppendLine(string.Join(separator, columnNameString));
                }
                if (columnString.Count > 0)
                {
                    content.AppendLine(string.Join(separator, columnString));
                }
            }
            return content.ToString();
        }

        /// <summary>
        /// DataTable转输出字符串
        /// </summary>
        /// <returns></returns>
        public static string ToOutputString(this DataTable? table, string separator = ",")
        {
            StringBuilder content = new StringBuilder();
            content.AppendLine($"{(string.IsNullOrEmpty(table?.TableName) ? "table" : table?.TableName)}:");
            List<string?> columnNameString = new List<string?>();

            if (table != null)
            {
                foreach (DataColumn dataColumn in table.Columns)
                {
                    if (dataColumn.Caption != dataColumn.ColumnName)
                    {
                        columnNameString.Add($"{dataColumn.ColumnName}({dataColumn.Caption})");
                    }
                    else
                    {
                        columnNameString.Add(dataColumn.ColumnName);
                    }
                }
                if (columnNameString.Count > 0)
                {
                    content.AppendLine(string.Join(separator, columnNameString));
                }
                foreach (DataRow dataRow in table.Rows)
                {
                    List<string?> lineString = new List<string?>();
                    foreach (DataColumn dataColumn in table.Columns)
                    {
                        lineString.Add(dataRow[dataColumn] == null ? "" : dataRow[dataColumn].ToString());
                    }
                    if (lineString.Count > 0)
                    {
                        content.AppendLine(string.Join(separator, lineString));
                    }
                }
            }
            return content.ToString();
        }


        /// <summary>
        /// DataSet转输出字符串
        /// </summary>
        /// <returns></returns>
        public static string ToOutputString(this DataSet dataSet, string separator = ",")
        {
            StringBuilder content = new StringBuilder();
            if (dataSet != null)
            {
                foreach (DataTable table in dataSet.Tables)
                {
                    content.AppendLine(table.ToOutputString(separator));
                    content.AppendLine("");
                }
            }
            return content.ToString();
        }

        /// <summary>
        /// 将DataRow转DataTable（行转列）
        /// </summary>
        /// <returns></returns>
        public static DataTable DataRowToDataTable(this DataRow row, string tableName = "")
        {
            DataTable dataTable = new DataTable();
            if (!string.IsNullOrEmpty(tableName))
            {
                dataTable.TableName = tableName;
            }
            DataColumn dcName = new DataColumn("列名", typeof(string));
            dataTable.Columns.Add(dcName);
            DataColumn dcCaption = new DataColumn("列说明", typeof(string));
            dataTable.Columns.Add(dcCaption);
            DataColumn dcValue = new DataColumn("值", typeof(string));
            dataTable.Columns.Add(dcValue);
            if (row != null)
            {
                foreach (DataColumn dc in row.Table.Columns)
                {
                    DataRow newRow = dataTable.NewRow();
                    newRow[dcName] = dc.ColumnName;
                    if (dc.ColumnName != dc.Caption)
                    {
                        newRow[dcCaption] = dc.Caption;
                    }
                    newRow[dcValue] = row[dc.ColumnName]?.ToString();
                    dataTable.Rows.Add(newRow);
                }
            }
            return dataTable;
        }


        /// <summary>
        /// 将DataTable Row 转DataTable并装箱到DataSet中（行转列）
        /// </summary>
        /// <param name="table"></param>
        /// <param name="tableNamePrefix">表名前缀</param>
        /// <returns></returns>
        public static DataSet DataTableRowToDataSet(this DataTable table, string tableNamePrefix = "table")
        {
            DataSet dataSet = new DataSet();
            if (table != null)
            {
                if (!string.IsNullOrEmpty(tableNamePrefix))
                {
                    tableNamePrefix = $"{tableNamePrefix}_";
                }
                else
                {
                    tableNamePrefix = "table_";
                }
                int sn = 0;
                foreach (DataRow row in table.Rows)
                {
                    sn++;
                    DataTable dataTable = row.DataRowToDataTable($"{tableNamePrefix}{sn}");
                    dataSet.Tables.Add(dataTable.Copy());
                }
            }
            return dataSet;
        }

        /// <summary>
        /// 设置列的Caption
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="columnName"></param>
        /// <param name="columnCaption"></param>
        public static void SetColumnCaption(this DataTable? dataTable, string columnName, string columnCaption)
        {
            if (dataTable?.Columns?.Contains(columnName) == true)
            {
#pragma warning disable CS8602 // 解引用可能出现空引用。
                dataTable.Columns[columnName].Caption = columnCaption;
#pragma warning restore CS8602 // 解引用可能出现空引用。
            }
        }

        /// <summary>
        /// 设置列序号
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="columnName"></param>
        /// <param name="order"></param>
        public static void SetColumnOrder(this DataTable? dataTable, string columnName, int order)
        {

            if (dataTable?.Columns?.Contains(columnName) == true)
            {
                DataColumn? dataColumn = dataTable.Columns[columnName];
                if (dataColumn != null)
                {
                    dataColumn.SetColumnOrder(order);
                }
            }
        }

        /// <summary>
        /// 移除列
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="columnName"></param>
        public static void RemoveColumn(this DataTable dataTable, string columnName)
        {

            if (dataTable.Columns.Contains(columnName))
            {
                dataTable.Columns.Remove(columnName);
            }
        }

        /// <summary>
        /// 新增列
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="columnName"></param>
        /// <param name="type"></param>
        public static void AddColumn(this DataTable dataTable, string columnName, Type? type = null)
        {

            if (!dataTable.Columns.Contains(columnName))
            {
                if (type == null)
                {
                    type = typeof(object);
                }
                DataColumn dataColumn = dataTable.Columns.Add(columnName, type);
            }
        }

        /// <summary>
        /// 新增列
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="columnName"></param>
        /// <param name="type"></param>
        /// <param name="columnCaption"></param>
        public static void AddColumn(this DataTable? dataTable, string columnName, string columnCaption, Type? type = null)
        {
            if (dataTable != null)
            {
                if (dataTable.Columns.Contains(columnName) == false)
                {
                    if (type == null)
                    {
                        type = typeof(object);
                    }
                    DataColumn dataColumn = dataTable.Columns.Add(columnName, type);
                    if (!string.IsNullOrEmpty(columnCaption))
                    {
                        dataColumn.Caption = columnCaption;
                    }
                }
                else
                {
                    if (dataTable.Columns.Contains(columnName) == true)
                    {
                        if (!string.IsNullOrEmpty(columnCaption))
                        {
#pragma warning disable CS8602 // 解引用可能出现空引用。
                            dataTable.Columns[columnName].Caption = columnCaption;
#pragma warning restore CS8602 // 解引用可能出现空引用。
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 设置列序号
        /// </summary>
        /// <param name="column"></param>
        /// <param name="order"></param>
        public static void SetColumnOrder(this DataColumn column, int order)
        {
            column.SetOrdinal(order);
        }

        /// <summary>
        /// 设置ReportX数据，数据永远填充第一行，用于报表常量注入
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="columnName"></param>
        /// <param name="value"></param>
        /// <param name="columnCaption">列标题</param>
        /// <param name="type">类型，为NULL则默认为string</param>
        public static bool SetFastReportData(this DataTable dataTable, string columnName, object? value = null, string columnCaption = "", Type? type = null)
        {
            try
            {
                if (dataTable == null)
                {
                    dataTable = new DataTable();
                }
                if (type == null)
                {
                    type = typeof(string);
                }
                dataTable.AddColumn(columnName, columnCaption, type);
                DataRow drFirst;
                if (dataTable.Rows.Count <= 0)
                {
                    drFirst = dataTable.NewRow();
                    dataTable.Rows.Add(drFirst);
                }
                drFirst = dataTable.Rows[0];
                drFirst[columnName] = value;
                drFirst.AcceptChanges();
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"设置FastReport数据失败，{ex.DetailInfo()}");
                return false;
            }
        }


        /// <summary>
        /// 获取CheckComBoxCtrl指定Checked状态的数据
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="isChecked"></param>
        /// <returns></returns>
        public static DataTable GetCheckComBoxCtrlCheckedStatusData(this DataTable dataTable, bool isChecked = true)
        {
            DataTable? res = new DataTable();
            if (dataTable != null)
            {
                res = dataTable.Clone();
                if (dataTable.Columns.Contains("IsChecked"))
                {
                    DataRow[] selectRow = dataTable.Select($" IsChecked = {isChecked} ");
                    if (selectRow?.Length > 0)
                    {
                        var copyRes = selectRow?.CopyToDataTable();
                        if(copyRes != null)
                        {
                            res = copyRes;
                        }
                    }
                }
            }
            return res;
        }

        /// <summary>
        /// 获取CheckComBoxCtrl指定Checked状态的数据
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="isChecked"></param>
        /// <returns></returns>
        public static IDictionary<TKey, TValue?> GetCheckComBoxCtrlCheckedStatusDictionaryData<TKey, TValue>(this DataTable dataTable, bool isChecked = true)
            where TKey : class,new()
            where TValue : class,new()
        {
            IDictionary<TKey, TValue?> res = new Dictionary<TKey, TValue?>();
            DataTable checkedData = dataTable.GetCheckComBoxCtrlCheckedStatusData(isChecked);
            res = checkedData.ToDictionary<TKey, TValue>("Key", "Value");
            return res;
        }

        /// <summary>
        /// 获取CheckComBoxCtrl指定Checked状态的行
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static IList<T?> ToList<T>(this DataTable dataTable, string columnName) where T : class
        {
            List<T?> res = new List<T?>();
            if (dataTable != null)
            {
                if (dataTable.Columns.Contains(columnName))
                {
                    foreach (DataRow row in dataTable.Rows)
                    {
                        object valObj = row[columnName];
                        T? valT = ValueTypeConvertHelper.ChangeType<T>(valObj, null);
                        res.Add(valT);
                    }
                }
            }
            return res;
        }

        /// <summary>
        /// 获取CheckComBoxCtrl指定Checked状态的行
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="keyColumnName"></param>
        /// <param name="valueColumnName"></param>
        /// <returns></returns>
        public static IDictionary<TKey, TValue?> ToDictionary<TKey, TValue>(this DataTable dataTable, string keyColumnName, string valueColumnName)
            where TKey : class
            where TValue : class
        {
            Dictionary<TKey, TValue?> res = new Dictionary<TKey, TValue?>();
            if (dataTable != null)
            {
                if (dataTable.Columns.Contains(keyColumnName) && dataTable.Columns.Contains(valueColumnName))
                {
                    foreach (DataRow row in dataTable.Rows)
                    {
                        object keyObj = row[keyColumnName];
                        object valObj = row[valueColumnName];
                        TKey? keyT = ValueTypeConvertHelper.ChangeType<TKey>(keyObj, null);
                        TValue? valT = ValueTypeConvertHelper.ChangeType<TValue>(valObj, null);
                        if (keyT != null)
                        {
                            if (!res.ContainsKey(keyT))
                            {
                                res.Add(keyT, valT);
                            }
                        }
                    }
                }
            }
            return res;
        }

        /// <summary>
        /// 设置DataTable Column的caption
        /// </summary>
        /// <returns></returns>
        public static DataTable SetDataTableColumnCaption<T>(this DataTable table) where T : new()
        {
            try
            {
                Type type = typeof(T);
                if (!string.IsNullOrEmpty(table.TableName))
                {
                    table.TableName = type.Name;
                }
                T t = new T();
                PropertyInfo[] propertyInfos = type.GetProperties();
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    if (table.Columns.Contains(propertyInfo.Name))
                    {
                        string? columnCaption = GetDescriptionAttribute(t, propertyInfo.Name);
                        if (!string.IsNullOrEmpty(columnCaption))
                        {
                            var tableColumn = table.Columns[propertyInfo.Name];
                            if (tableColumn != null)
                            {
                                tableColumn.Caption = columnCaption;
                            }
                        }
                    }
                }
                return table;
            }
            catch (Exception ex)
            {
                throw new Exception($"将List<Model>转换为DataTable出错：{Environment.NewLine}{ex.Message}");
            }
        }

        /// <summary>
        /// 获取DataRow指定行的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="row"></param>
        /// <param name="columnName"></param>
        /// <param name="defaultValue">defaultValue</param>
        /// <returns></returns>
        public static T? GetRowColumnData<T>(this DataRow row,string columnName,T? defaultValue = default)
        {
            T? res = default;
            if(row.Table.Columns.Contains(columnName))
            {
                object data = row[columnName];
                res = ValueTypeConvertHelper.ChangeType<T>(data, defaultValue); //Convert.ChangeType(data, typeof(T));
            }
            return res;
        }
        #endregion

        #region 反射相关

        /// <summary>
        /// 将T属性值输出为字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="classInstance"></param>
        /// <returns></returns>
        public static string ToOutputString<T>(this T classInstance) where T : class
        {

            StringBuilder outputString = new StringBuilder();
            if (classInstance != null)
            {
                PropertyInfo[] pArray = classInstance.GetType().GetProperties();
                if (pArray != null && pArray.Count() > 0)
                {
                    foreach (var p in pArray)
                    {
                        //获取描述
                        object[] attrsDesc = p.GetCustomAttributes(typeof(DescriptionAttribute), false);
                        string name = p.Name;
                        string? desc = "";
                        if (attrsDesc != null && attrsDesc.Count() > 0)
                        {
                            desc = (attrsDesc.First() as DescriptionAttribute)?.Description;
                        }
                        if (string.IsNullOrEmpty(desc))
                        {
                            desc = $" //{desc}";
                        }
                        object? valueObj = p.GetValue(classInstance, null);
                        string? value = "";
                        if (valueObj == null)
                        {
                            value = "[NULL]";
                        }
                        else
                        {
                            value = valueObj?.ToString();
                        }
                        outputString.AppendLine($" {name} = {value} ;{desc} ");
                    }
                }

                FieldInfo[] fArray = classInstance.GetType().GetFields();
                if (fArray != null && fArray.Count() > 0)
                {
                    foreach (FieldInfo fi in fArray)
                    {
                        object[] attrsDesc = fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
                        string? desc = "";
                        if (attrsDesc != null && attrsDesc.Count() > 0)
                        {
                            desc = (attrsDesc.First() as DescriptionAttribute)?.Description;
                        }
                        if (string.IsNullOrEmpty(desc))
                        {
                            desc = $" //{desc}";
                        }
                        object? valueObj = fi.GetValue(classInstance);
                        string? value = "";
                        if (valueObj == null)
                        {
                            value = "[NULL]";
                        }
                        else
                        {
                            value = valueObj?.ToString();
                        }
                        outputString.AppendLine($" {fi.Name} = {value} ;{desc} ");
                    }
                }
            }
            return outputString.ToString();
        }


        /// <summary>
        /// 将IList&lt;T&gt;属性值输出为字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listClassInstance"></param>
        /// <returns></returns>
        public static string ToOutputString<T>(this IList<T> listClassInstance) where T : class
        {
            StringBuilder outputString = new StringBuilder();
            if (listClassInstance != null)
            {
                foreach(var item in listClassInstance)
                {
                    outputString.AppendLine(item.ToOutputString());
                    outputString.AppendLine($"{Environment.NewLine}");
                }
            }
            return outputString.ToString();
        }

        /// <summary>
        /// 确定指定的类型可以为空
        /// </summary>
        public static bool IsNullable(Type t)
        {
            return !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
        }

        /// <summary>
        /// 如果类型为"空"，则返回基础类型，否则返回类型
        /// </summary>
        public static Type? GetCoreType(Type t)
        {
            if (t != null && IsNullable(t))
            {
                if (!t.IsValueType)
                {
                    return t;
                }
                else
                {
                    return Nullable.GetUnderlyingType(t);
                }
            }
            else
            {
                return t;
            }
        }

        ///// <summary>
        ///// 获取DataMemberAttribute
        ///// </summary>
        ///// <param name="dataModel"></param>
        ///// <param name="propertyInfoName"></param>
        ///// <returns></returns>
        //public static string GetDataMemberAttribute(this DataModelBase dataModel, string propertyInfoName)
        //{
        //    string res = propertyInfoName;
        //    try
        //    {
        //        PropertyInfo pi = dataModel.GetType().GetProperty(propertyInfoName);
        //        if (pi == null)
        //        {
        //            FieldInfo fieldInfo = dataModel.GetType().GetField(propertyInfoName);
        //            object[] attributeObjs = fieldInfo.GetCustomAttributes(false);
        //            foreach (var item in attributeObjs)
        //            {
        //                if (item is DataMemberAttribute dataMemberAttribute)
        //                {
        //                    res = dataMemberAttribute.Name;
        //                    break;
        //                }
        //            }
        //        }
        //        else
        //        {
        //            object[] attributeObjs = pi.GetCustomAttributes(false);
        //            foreach (var item in attributeObjs)
        //            {
        //                if (item is DataMemberAttribute dataMemberAttribute)
        //                {
        //                    res = dataMemberAttribute.Name;
        //                    break;
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {

        //    }
        //    return res;
        //}

        /// <summary>
        /// 获取属性描述，获取失败返回属性本身的名称
        /// </summary>
        /// <param name="model"></param>
        /// <param name="propertyInfoName"></param>
        /// <returns></returns>
        public static string? GetDescriptionAttribute<T>(this T model, string propertyInfoName) where T : new()
        {
            string? res = propertyInfoName;
            try
            {
                if (model != null)
                {
                    AttributeCollection? attributes = TypeDescriptor.GetProperties(model)[propertyInfoName]?.Attributes;
                    if(attributes != null)
                    {
                        DescriptionAttribute? myAttribute = (DescriptionAttribute?)attributes[typeof(DescriptionAttribute)];
                        res = myAttribute?.Description;
                    }
                }
            }
            catch (Exception ex)
            {

            }
            return res;
        }

        /// <summary>
        /// 获取数据的附加属性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <param name="propertyInfoName"></param>
        /// <returns></returns>
        public static string? GetDataMemberAttribute<T>(this T? model, string propertyInfoName) where T : new()
        {
            string? res = propertyInfoName;
            try
            {
                PropertyInfo? pi = model?.GetType().GetProperty(propertyInfoName);
                if (pi == null)
                {
                    FieldInfo? fieldInfo = model?.GetType().GetField(propertyInfoName);
                    if (fieldInfo != null)
                    {
                        DataMemberAttribute? dmAttr = (DataMemberAttribute)fieldInfo.GetCustomAttributes(false)[0];
                        res = dmAttr?.Name;
                    }
                }
                else
                {
                    DataMemberAttribute? dmAttr = (DataMemberAttribute)pi.GetCustomAttributes(false)[0];
                    res = dmAttr?.Name;
                }
            }
            catch (Exception ex)
            {

            }
            return res;
        }
        #endregion 反射相关

        #region Lambda

        /// <summary>
        /// 用法 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <code>
        ///  Expression&lt;Func&lt;Movies, bool&gt;&gt; expression = t =&gt; true;
        ///  expression = expression.And(t =&gt; t.MName == name);
        ///  db.Movies.Where(expression.Compile()).AsQueryable().ToList();
        /// </code>
        /// <returns></returns>
        public static Expression<Func<T, bool>> True<T>()
        {
            return f => true;
        }

        /// <summary>
        /// 用法 
        ///  Expression&lt;Func&lt;Movies, bool&gt;&gt; expression = t =&gt; true;
        ///  expression = expression.And(t =&gt; t.MName == name);
        ///  db.Movies.Where(expression.Compile()).AsQueryable().ToList();
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static Expression<Func<T, bool>> False<T>()
        {
            return f => false;
        }

        /// <summary>
        /// 用法 
        ///  Expression&lt;Func&lt;Movies,bool&gt;&gt; expression = t =&gt; true;
        ///  expression = expression.And(t =&gt; t.MName == name);
        ///  db.Movies.Where(expression.Compile()).AsQueryable().ToList();
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression1"></param>
        /// <param name="expression2"></param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
        {
            var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression), expression1.Parameters);
        }

        /// <summary>
        /// 用法 
        ///  Expression&lt;Func&lt;Movies,bool&gt;&gt; expression = t =&gt; true;
        ///  expression = expression.And(t =&gt; t.MName == name);
        ///  db.Movies.Where(expression.Compile()).AsQueryable().ToList();
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression1"></param>
        /// <param name="expression2"></param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
        {
            var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters);
        }
        #endregion Lambda

        #region 拷贝相关
        /// <summary>
        /// 使用JSON的方式深拷贝
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static T DeepCopyByJson<T>(this T? data) where T : class,new()
        {
            var res = JsonHelper.Deserialize<T>(JsonHelper.Serialize(data, useJsonOriginalPropertyContractResolver:true),true);
            if(res == null)
            {
                res = new T();
            }
            return res;
        }

        /// <summary>
        /// 反射深拷贝
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public static object? DeepCopyByReflection(this object? model)
        {
            var modelType = model?.GetType();
            if (modelType != null && modelType.IsValueType)
            {
                return model;
            }
            if (modelType?.Name == typeof(List<>).Name)
            {
                var genericType = modelType.GenericTypeArguments;
                if (genericType != null && genericType.Count() > 0)
                {
#pragma warning disable CS8604 // 引用类型参数可能为 null。
                    var newObj = Activator.CreateInstance(genericType.FirstOrDefault());
#pragma warning restore CS8604 // 引用类型参数可能为 null。
                    var newList = (IList?)Activator.CreateInstance(modelType);
                    if (newList != null && newObj != null && model != null)
                    {
                        foreach (var itemObj in (IList)model)
                        {
                            //newList.Add(itemObj.Clone());
                            newList.Add(DeepCopyByReflection(itemObj));
                        }
                    }
                    return newList;
                }
            }
            if (modelType?.Name == typeof(Dictionary<,>).Name)
            {
                var genericType = modelType.GenericTypeArguments;
                var newkey = Activator.CreateInstance(genericType[0]);
                var newValue = Activator.CreateInstance(genericType[1]);
                var newDic = (IDictionary?)Activator.CreateInstance(modelType);
                var modelDic = (IDictionary?)model;
                if (newDic != null && modelDic != null)
                {
                    foreach (var itemkey in (modelDic.Keys))
                    {
                        //newDic.Add(itemkey.Clone(), modelDic[itemkey].Clone());
#pragma warning disable CS8604 // 引用类型参数可能为 null。
                        newDic.Add(DeepCopyByReflection(itemkey), DeepCopyByReflection(modelDic[itemkey]));
#pragma warning restore CS8604 // 引用类型参数可能为 null。
                    }
                }
                return newDic;
            }
            var pros = modelType?.GetProperties();
#pragma warning disable CS8604 // 引用类型参数可能为 null。
            var newModel = Activator.CreateInstance(modelType, true);
#pragma warning restore CS8604 // 引用类型参数可能为 null。
            var newModelType = newModel?.GetType();
            var newpros = newModelType?.GetProperties();
            if (pros != null)
            {
                foreach (var pro in pros)
                {
                    var newPro = newpros?.FirstOrDefault(u => u.Name == pro.Name);
                    if (newPro != null)
                    {
                        if (pro.PropertyType.IsValueType || pro.PropertyType == typeof(string))
                        {
                            var value = pro.GetValue(model);
                            newPro.SetValue(newModel, value);
                        }
                        else
                        {
                            var value = pro.GetValue(model);
#pragma warning disable CS8604 // 引用类型参数可能为 null。
                            var actobj = Activator.CreateInstance(newPro?.PropertyType, true);
#pragma warning restore CS8604 // 引用类型参数可能为 null。
                            newPro.SetValue(newModel, DeepCopyByReflection(value));
                        }
                    }
                }
            }
            return newModel;
        }


        /// <summary>
        /// 深拷贝 之前为反射拷贝，后替换为Newtonsoft.Json原始属性进行拷贝
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static T DeepCopyByReflectionT<T>(this T source) where T : new()
        {
            if (source == null)
                return source;
            
            // 创建新对象实例
            T? clone = default(T);//Activator.CreateInstance<T>();
            
            string json = JsonConvert.SerializeObject(source, new JsonSerializerSettings
            {
                ContractResolver = new DeepCopyContractResolver()
            });

            clone = JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings
            {
                ContractResolver = new DeepCopyContractResolver()
            });
            return clone ?? new T();
        }
        #endregion 拷贝相关
    }
}